/*
 * Copyright 2012 Claude Houle claude.houle@gmail.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.code.mochaccino.framework.security;

import com.google.code.mochaccino.framework.security.jaxrs.impl.AccountExceptionMapper;
import com.google.code.mochaccino.framework.security.jaxrs.impl.AuthenticationExceptionMapper;
import com.google.code.mochaccino.framework.security.jaxrs.impl.AuthorizationExceptionMapper;
import com.google.code.mochaccino.framework.security.jaxrs.impl.ConcurrentAccessExceptionMapper;
import com.google.code.mochaccino.framework.security.jaxrs.impl.CredentialsExceptionMapper;
import com.google.code.mochaccino.framework.security.jaxrs.impl.DisabledAccountExceptionMapper;
import com.google.code.mochaccino.framework.security.jaxrs.impl.ExcessiveAttemptsExceptionMapper;
import com.google.code.mochaccino.framework.security.jaxrs.impl.ExecutionExceptionMapper;
import com.google.code.mochaccino.framework.security.jaxrs.impl.ShiroExceptionMapper;
import com.google.code.mochaccino.framework.security.jaxrs.impl.UnauthenticatedExceptionMapper;
import com.google.code.mochaccino.framework.security.jaxrs.impl.UnauthorizedExceptionMapper;
import com.google.code.mochaccino.framework.security.jaxrs.impl.UnknownAccountExceptionMapper;
import com.google.code.mochaccino.framework.security.jaxrs.impl.UnsupportedTokenExceptionMapper;
import com.google.common.base.Preconditions;
import com.google.inject.AbstractModule;
import java.net.URI;
import java.net.URISyntaxException;
import javax.inject.Singleton;
import javax.ws.rs.core.MediaType;

/**
 * A exception mapper module for JAXRS that will bind exception mapping classes for all
 * known exceptions for Shiro. While these default should be enough for most cases, there
 * may be user-defined use-case where you will need to bind your own mappers instead of the defaults.
 * <p/>
 * <p/>
 * <p/>
 * These are provided as convenience only.
 */
public class SecurityExceptionMapperModule extends AbstractModule {

	private URI       loginURL                     = null;
	private String    forbiddenMessage             = null;
	private MediaType forbiddenMessageMediaType    = null;
	private String    unauthorizedMessage          = null;
	private MediaType unauthorizedMessageMediaType = null;

	public SecurityExceptionMapperModule( String login, String forbiddenMessage, MediaType forbiddenMessageMediaType, String unauthorizedMessage, MediaType unauthorizedMessageMediaType ) {
		try {
			this.loginURL = new URI( Preconditions.checkNotNull( login ) );
		} catch ( URISyntaxException e ) {
			throw new RuntimeException( e );
		}
		this.forbiddenMessage = Preconditions.checkNotNull( forbiddenMessage );
		this.forbiddenMessageMediaType = Preconditions.checkNotNull( forbiddenMessageMediaType );
		this.unauthorizedMessage = Preconditions.checkNotNull( unauthorizedMessage );
		this.unauthorizedMessageMediaType = Preconditions.checkNotNull( unauthorizedMessageMediaType );
	}

	@Override
	protected void configure() {

		// Server Error
		bind( AccountExceptionMapper.class ).in( Singleton.class );
		bind( AuthenticationExceptionMapper.class ).in( Singleton.class );
		bind( AuthorizationExceptionMapper.class ).in( Singleton.class );
		bind( ConcurrentAccessExceptionMapper.class ).in( Singleton.class );
		bind( ExecutionExceptionMapper.class ).in( Singleton.class );
		bind( ShiroExceptionMapper.class ).in( Singleton.class );
		bind( UnsupportedTokenExceptionMapper.class ).in( Singleton.class );

		// Redirect
		bind( UnauthenticatedExceptionMapper.class ).toInstance( new UnauthenticatedExceptionMapper( loginURL ) );
		bind( CredentialsExceptionMapper.class ).toInstance( new CredentialsExceptionMapper( loginURL ) );
		bind( UnknownAccountExceptionMapper.class ).toInstance( new UnknownAccountExceptionMapper( loginURL ) );

		// Forbidden
		bind( DisabledAccountExceptionMapper.class ).toInstance( new DisabledAccountExceptionMapper( forbiddenMessage, forbiddenMessageMediaType ) );
		bind( ExcessiveAttemptsExceptionMapper.class ).toInstance( new ExcessiveAttemptsExceptionMapper( forbiddenMessage, forbiddenMessageMediaType ) );

		// Unauthorized
		bind( UnauthorizedExceptionMapper.class ).toInstance( new UnauthorizedExceptionMapper( unauthorizedMessage, unauthorizedMessageMediaType ) );
	}
}
